/********************************************
 * 功能说明: 
 * 模块名称: 
 * 系统名称: 
 * 软件版权: 
 * 系统版本: 1.0.0
 * 开发人员: zhangfb
 * 开发时间: 2019/4/17 23:15
 * 审核人员: 
 * 相关文档: 
 * 修改记录: 修改日期 修改人员 修改说明
 *********************************************/
package com.hyacinth.seckill.web;

import com.hyacinth.seckill.service.OrderService;
import com.hyacinth.seckill.service.SeckillService;
import com.hyacinth.wapper.RetValue;
import com.hyacinth.wapper.WrapMapper;
import com.hyacinth.wapper.Wrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 秒杀控制器
 * @author zhangfb
 * @version 1.0.0.1
 * @since JDK 1.8
 */
@Api(tags ="秒杀")
@RestController
@RequestMapping("/seckill")
public class SeckillController {

    private final static Logger LOGGER = LoggerFactory.getLogger(SeckillController.class);

    private static int corePoolSize = Runtime.getRuntime().availableProcessors();
    //创建线程池  调整队列数 拒绝服务
    private static ThreadPoolExecutor executor  = new ThreadPoolExecutor(corePoolSize, corePoolSize+1, 10, TimeUnit.SECONDS,
            new LinkedBlockingQueue<Runnable>(1000));

    @Autowired
    private OrderService orderService;
    @Autowired
    private SeckillService seckillService;

    @ApiOperation(value="秒杀实现一", nickname="张凡斌的秒杀实践")
    @PostMapping("/start")
    public Wrapper start(long goodsId){
        LOGGER.info("开始秒杀一");
        int skillNum = 1000;
        final CountDownLatch latch = new CountDownLatch(skillNum);//N个购买者
        final long killId =  goodsId;
        for(int i=0; i<skillNum; i++){
            final long userId = i;
            Runnable task = new Runnable() {
                @Override
                public void run() {
                    RetValue ret = seckillService.startSeckill(killId, userId);
                    if(ret.isSuccess()){
                        LOGGER.info("用户:{}{}", userId, "秒杀成功");
                    }else{
                        LOGGER.info("用户:{}{}", userId, "哎呦喂，人也太多了，请稍后！");
                    }
                    latch.countDown();
                }
            };
            executor.execute(task);
        }
        try {
            latch.await();// 等待所有人任务结束
            Long seckillCount = orderService.sumKilledCount(killId);
            LOGGER.info("一共秒杀出{}件商品",seckillCount);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        LOGGER.info("结束秒杀一");
        return WrapMapper.ok();
    }
}
